<template>
  <div class="main-view base64-to-file-view">
    <div class="title">base64还原成文件</div>
    <div class="base64-code">
      <div>
        <el-input v-model="state.base64.data" type="textarea" :rows="10"></el-input>
      </div>
      <div style="padding-top: 5px">
        <el-button type="primary" @click="onRevert">还原</el-button>
        <el-button type="danger" @click="onClear">清空</el-button>
      </div>
    </div>
    <el-scrollbar :max-height="getMaxHeight" always>
      <div class="file-list">
        <div v-for="(item, idx) in state.list" :key="idx" class="file-item">
          <div class="info">
            <el-image v-if="item.image" :src="item.data"></el-image>
            <div v-else>无法预览</div>
          </div>
          <div class="footer">
            <div class="file-name"></div>
            <div class="file-buttons">
              <el-button size="small" type="primary" @click="onDownload(item.data)">下载</el-button>
            </div>
          </div>
        </div>
      </div>
    </el-scrollbar>
  </div>
</template>

<script setup lang="ts">
import { computed, reactive } from 'vue';

const state = reactive<{
  base64: {
    data: string;
  };
  list: Array<{ name: string; data: string; image: boolean }>;
}>({
  base64: {
    data: ''
  },
  list: []
});

const getMaxHeight = computed(() => {
  return document.body.offsetHeight - 50 - 30 - 320;
});

const isImage = (dataString) => {
  // 正则表达式匹配Base64图片的开头
  const regex = /^data:image\/([a-z]+);base64,/;
  // 测试字符串是否匹配
  return regex.test(dataString);
};

const onRevert = () => {
  state.list.push({
    name: '1.npg',
    data: state.base64.data,
    image: isImage(state.base64.data)
  });
};

const onClear = () => {
  state.list.splice(0, state.list.length);
};

const onDownload = (data: string) => {
  const arr: string[] = data.split(','); // 对base64文件进行字符串分割
  const contentType = arr[0].split(':')[1]; // 获取文件type
  const raw = window.atob(arr[1]); // 获取base64文件编码
  const rawLength = raw.length;
  const uInt8Array = new Uint8Array(rawLength);

  for (let i = 0; i < rawLength; ++i) {
    uInt8Array[i] = raw.charCodeAt(i);
  }

  // 将base64字符串转换为Blob对象
  const blob = new Blob([uInt8Array], { type: contentType });

  // 创建一个指向Blob对象的URL
  const blobUrl = URL.createObjectURL(blob);

  // 创建一个a标签用于触发下载
  const a = document.createElement('a');
  a.href = blobUrl;
  a.download = 'file';
  document.body.appendChild(a);
  a.click();

  // 清理临时的URL对象和a标签
  document.body.removeChild(a);
  URL.revokeObjectURL(blobUrl);
};
</script>

<style scoped lang="scss">
.base64-to-file-view {
  .title {
    height: 50px;
    line-height: 50px;
    margin-bottom: 5px;
    font-size: 18px;
  }

  .file-list {
    display: flex;
    flex-wrap: wrap;

    .file-item {
      width: 300px;
      height: 220px;
      border: 1px solid var(--border-color);
      border-radius: 2px;
      margin-top: 5px;
      margin-left: 5px;

      .info {
        width: 300px;
        height: 180px;
      }

      .footer {
        display: flex;
        flex-direction: row;
        height: 40px;
        line-height: 40px;
      }

      .file-name {
        flex: 1;
      }

      .file-buttons {
        padding-left: 5px;
        padding-right: 5px;
      }
    }
  }
}
</style>
